Quarto: a very short introduction

Iryna Schlackow; SDI/EPS

2025-08-06

What is Quarto?

  • Quarto is an open-source scientific and technical publishing system;
  • can be used to create reports, dashboards, presentations, websites;
  • possible to mix text and executable code (R, Python);
  • output is dynamic and reproducible;
  • useful for repetitive and data-driven reporting.

Example: admissions reports

Image from https://oxfordvisit.com/articles/harry-potter-filming-locations-great-hall-christ-church/1
  • During each admissions cycle, tutors look at the application cohort, e.g.

    • number and sociodemographic profile of applicants;

    • distribution of admissions measures by characteristics of interest (gender, deprivation status, schooling);

    • comparisons with previous years and/or across the university.

  • Ca. 40 descriptive statistics reports are produced each year:

    • very similar in structure… but not the same!

Example report: one admissions metric

Example report: two admissions metrics

Example report: comparison across admissions years

Copy-pasting approach

  • error-prone;
  • different faculty requirements;
  • not scalable: single database update / requirement change require re-generation of the whole report suite.


Can the workflow be made more efficient?

What parts of the workflow can be automated?

Example automation

Example automation

Example automation

How can Quarto help?

  • Report is parameterised (e.g. input database, UCAS cycle, document style, repetitive footnote string, characteristic of interest);

  • one-click update at database change (e.g. bug fixes);

  • one analysis, multiple formats (e.g. pdf output; links colour; missing data display);

  • possible to include executable analysis code, so all numbers are reproducible;

  • cross-referencing, interactive graphs, integration with R, Python, LaTeX…

How to get started

  • Install software: Quarto; text editor (Posit/RStudio, Positron, VS Code); R, Python.
  • Create a script:
    • typically a .qmd file;
    • YAML (document settings);
    • main body (text, figures, tables);
    • further documents (e.g. .css files).
  • Render (or preview).
  • Output formats:
    • .html: interactive and good for complex structure;
    • .pdf: print-ready;
    • .docx: for collaboration.

YAML (YAML Ain’t Markup Language)

  • Human-friendly way to specify document settings;
  • front matter at the top of the file;
  • use three dashes --- to start and end the YAML block.
---
title: "My first Quarto report"
author: "Jane Doe"
format: html
---

YAML for this presentation

---
title: "Quarto: a very short introduction"
author: "Iryna Schlackow; SDI/EPS"
date: "06 August 2025"
format: 
  revealjs:                    # output is .html slides
    smaller: true              # scale down default fonts
    css: styles.css            # further adjustments of the default style
    slide-number: "c/t"        # slide numbering
    embed-resources: true      # embed all figures so that .html can be shared
    code-copy: true            # add button for copying code
    code-block-bg: "#d0dff2"   # style of coding blocks
    code-block-border-left: "#002147"
    highlight-style: github
execute:                      # code execution options to prevent unwanted messages
  echo: false
  warning: false
  message: false
fig-cap-location: top         # figure captions above
tbl-cap-location: top         # table captions above
---

Main body

Lists and fonts

* You
* can
* create
  - nested
* lists

1. also text in **bold** and *italic*, and
1. numbered items
  • You
  • can
  • create
    • nested
  • lists


  1. also text in bold and italic, and

  2. numbered items

Tables

data <- data.frame(
  name = c("Alice", "Bob", "Charlie"),
  score = c(90, 85, 88),
  score2 = c(54, 20, 60))
  
kable(data, caption = "PAT scores")


PAT scores
name score1 score2
Alice 90 54
Bob 85 20
Charlie 88 60

Tables

data <- data.frame(
  name = c("Alice", "Bob", "Charlie"),
  score = c(90, 85, 88))
  
kable(data, caption = "PAT scores") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "responsive", "condensed")) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#002147") %>%
  add_header_above(c(" " = 1, "PAT score" = 2)) %>%
  pack_rows("Female students", 1, 1) %>% 
  pack_rows("Male students", 2, 3)


PAT score
name score1 score2
Female students
Alice 90 54
Male students
Bob 85 20
Charlie 88 60

Cross-referencing

# We can do numbered sections {#sec-numbered}

## With numbered subsection {#sec-numbered-subsection}

![Rewley House on Wellington Square.](https://upload.wikimedia.org/wikipedia/commons/a/a1/Rewley_House_-_geograph.org.uk_-_1126209.jpg){#fig-rewley}

See @fig-rewley from @sec-numbered-subsection for the buildings near the University Offices.

# AND we can do unnumbered sections! {.unnumbered}

Tabsets

::: {.panel-tabset}

##### First tab

This is in the first tab.

##### Second tab

This is in the second tab. We can also add graphs and tables here. And even write inline $\exp^{\textrm{i}\pi} = -1$ and displaymath $\LaTeX$ equations $$\sum_{i=1}^\infty \frac{1}{i^2} = \frac{\pi^2}{6}.$$

:::

Which looks like this:

Example HTML output

Engineering gender gap report

Example dashboard

Penguin dashboard; courtesy of Craig Smith & Connair Russell-Wilks (UAO).

How much coding is required?

  • It depends! Not much for basic reporting.
  • There are cheat sheets for everything.
  • Embedded analyses require R (or Python).
  • Fine-tuning display options might need CSS.
  • AI can help (code snippets; within-editor integration).

The concept of gRammar

  • Many R packages use grammar to build complex outputs from simple components.
  • A consistent set of verbs is used to perform data manipulation.
  • Output is constructed step-by-step by putting these verbs into layers.
  • Layers are connected by %>% or +.

E.g. tidyverse (data manipulation):
dataset %>% filter(...) %>% mutate(...) %>% summarise(...)

E.g. kableExtra (tables):
knitr::kable() %>% kable_styling() %>% add_header_above()

E.g. ggplot2 (plots):
ggplot(data, aes(...)) + geom_point() + facet_wrap() + theme_minimal()

Summary: the benefits of Quarto

  • Output reproducibility;
  • automation of repetitive reports;
  • structured and consistent formatting with themes and templates;
  • software integration (R, Python, CSS);
  • lots of random cool features;
  • version control;
  • learning curve but lots of documentation, cheat sheets and AI help.
Thank you
GIF from https://media.giphy.com/media/13HgwGsXF0aiGY/giphy.gif